package com.yzd.learnjava.enumerated;

import java.util.Iterator;

import com.yzd.learnjava.util.Enums;
import com.yzd.learnjava.util.Print;

public class PostOffice {
	enum MailHandler{
		GENERAL_DELIVERY{
			boolean handle(Mail m) {
				switch (m.generalDelivery) {
				case YES:
					Print.print("using general delivery for " + m);
					return true;

				default:
					return false;
				}
			}
		},
		
		MATCH_SCAN{
			boolean handle(Mail m) {
				switch (m.scannability) {
				case UNSCANABLE:
					return false;
				default:
					switch (m.address) {
					case INCORRECT:
						return false;
					default:
						Print.print("Delivery " + m + " automatically");
						return true;
					}
				}
			}
		},
		
		VISUAL_INSPECTION{
			boolean handle(Mail m) {
				switch (m.readability) {
				case ILLEGIBLE:
					return false;
				default:
					switch (m.address) {
					case INCORRECT:
						return false;
					default:
						Print.print("Delivery " + m + " normally");
						return true;
					}
				}
			}
		},
		
		RETURN_TO_SENDER{
			boolean handle(Mail m) {
				switch (m.returnAddress) {
				case MISSING:
					return false;
				default:
					Print.print("Returning " + m + " to sender");
					return true;
				}
			}
		};
		
		abstract boolean handle(Mail m);
	}
	static void handleMail(Mail m) {
		for(MailHandler handler : MailHandler.values()) {
			if(handler.handle(m)) {
				return;
			}
		}
		Print.print(m + " is a dead letter");
	}
	public static void main(String[] args) {
		for(Mail m : Mail.generator(10)) {
			Print.print(m.details());
			handleMail(m);
			Print.print("*****************");
		}
	}
}

class Mail{
	enum GeneralDelivery{
		YES, NO1, NO2, NO3, NO4, NO5
	}
	
	enum Scannability{
		UNSCANABLE, YES1, YES2, YES3, YES4
	}
	
	enum Readability{
		ILLEGIBLE,YES1, YES2, YES3, YES4
	}
	
	enum Address{
		INCORRECT, OK1, OK2, OK3, OK4, OK5, OK6
	}
	
	enum ReturnAddress{
		MISSING, OK1, OK2, OK3, OK4, OK5
	}
	
	GeneralDelivery generalDelivery;
	Scannability scannability;
	Readability readability;
	Address address;
	ReturnAddress returnAddress;
	
	static long counter = 0;
	long id = counter++;
	public String toString() {
		return "Mail " + id;
	} 
	
	public String details() {
		return toString() + ", General Delivery : " + generalDelivery 
				+ ", Address Scanability : " + scannability
				+ ", Address Readability : " + readability
				+ ", Address Address : " + address
				+ ", Return Address : " + returnAddress;
	}
	
	public static Mail randomMail() {
		Mail m = new Mail();
		m.generalDelivery = Enums.random(GeneralDelivery.class);
		m.scannability = Enums.random(Scannability.class);
		m.readability = Enums.random(Readability.class);
		m.address = Enums.random(Address.class);
		m.returnAddress = Enums.random(ReturnAddress.class);
		return m;
	}
	
	public static Iterable<Mail> generator(final int count){
		return new Iterable<Mail>() {
			int n = count;
			public Iterator<Mail> iterator() {
				return new Iterator<Mail>() {
					public boolean hasNext() {
						return n-- > 0;
					}
					public Mail next() {
						return randomMail();
					}
					
					public void remove() {
						throw new UnsupportedOperationException();
					}
				};
			}
		};
	}
	
}
